UNION Operator

The union command is used to do multiple queries at once. By using union, Both queries will return a single table.

For Example:

Let's use the countries table and regions table for this example. Refer Introduction to know about this table and the database.

select region_id from regions union select region_id from countries;

Here, we are executing two queries and combining them using union. This query will return region_id from both the tables without duplicate values.

Result:

In union,

  • The column names must be the same in both queries. Using different column names will result in an error.
  • Both columns should have the same data types.

To include duplicates, use union all.

union all

union all will return duplicate values as well.

For Example:

select region_id from regions union all select region_id from countries;

Result:

Ecto query for union

union/2

In Ecto union/2 allows you to combine multiple queries. union/2 expects two arguments. So let's create two queries and combine them using the union/2 function.

Expression example

For example:

First query,

region_id_from_country =
HR.Country
|> select([c], %{"region_id" => c.region_id})

Here, we are selecting region_id from HR.Country and assigning it to a variable called region_id_from_country. Here c is the reference variable; refer Aliases in Ecto to know about reference variables.

second query,

region_id_from_region =
HR.Region
|> select([r], %{"region_id" => r.region_id})

Here, we are selecting region_id from HR.Region and assigning it to a variable called region_id_from_region. We are putting both queries in a map data structure using %{}. Let's combine both queries.

union(region_id_from_country, ^region_id_from_region)
|> HR.Repo.all()

Here, we are combining both queries. Union expects its second argument to contain the ^ symbol to indicate that the argument is already defined.

Result:

Keyword example

first query,

region_id_from_country = from c in HR.Country, select: %{"region_id" => c.region_id}

second query,

region_id_from_region = from c in HR.Region, select: %{"region_id" => c.region_id}, union: ^region_id_from_country
HR.Repo.all(region_id_from_region)

union_all

As we mentioned, the result is returned in a map %{}. To include duplicate values, use union_all/2 function.

 union_all(region_id_from_country, ^region_id_from_region) |> HR.Repo.all()

Result:

Keyword example

Change union to union_all for the keywords syntax.